/**
 * 角色
 */
const { validationResult } = require('express-validator');
const config = require('@root/config/index');
const { poolPromise } = require('@root/db/index');
const { validateParams } = require('@root/utils/peak-tools.js');
const { httpStatusCode } = require('@root/types/HttpStatusCode.js');

/**
 * 获取角色
 */
async function selectRoleList(req, res, next) {
  if (validateParams({ req, res, validationResult })) return;
  try {
    const { role_name = '', sort = 'asc' } = req.query;
    const select_role_sql = `select * from sys_role where role_name like '%${role_name}%' order by role_sort ${sort}`;
    let [list] = await poolPromise.execute(select_role_sql);
    res.status(200).json({
      code: 200,
      msg: '获取角色成功',
      data: list,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * 添加角色
 */
async function insertRole(req, res, next) {
  if (validateParams({ req, res, validationResult })) return;
  try {
    const { role_name, role_key, role_sort, remark, status = 1 } = req.body;
    const { nickname } = req.auth;
    const [keys] = await poolPromise.execute(`select role_key from sys_role where role_key=?`, [
      role_key,
    ]);
    if (keys.length) {
      return res.status(httpStatusCode.Conflict).json({
        code: httpStatusCode.Conflict,
        msg: '角色标识已存在',
        data: null,
      });
    }

    const select_role_sql = `select role_name from sys_role where role_name=?`;
    let [list] = await poolPromise.query(select_role_sql, [role_name]);
    if (list.length) {
      return res.status(httpStatusCode.Conflict).json({
        code: httpStatusCode.Conflict,
        msg: '角色名已存在',
        data: null,
      });
    }
    const insert_role_sql = `insert into sys_role(role_name,role_key,role_sort,status,remark,create_by) values(?,?,?,?,?,?)`;
    let [{ affectedRows: role_affectedRows }] = await poolPromise.execute(insert_role_sql, [
      role_name,
      role_key,
      role_sort,
      status,
      remark,
      nickname,
    ]);
    if (!role_affectedRows) {
      return res.status(500).json({
        code: 500,
        msg: '添加角色失败',
        data: null,
      });
    }
    res.status(200).json({
      code: 200,
      msg: '添加角色成功',
    });
  } catch (error) {
    next(error);
  }
}

/**
 * 删除角色
 */
async function deleteRole(req, res, next) {
  if (validateParams({ req, res, validationResult })) return;
  try {
    const { ids } = req.body;
    const delete_role_sql = `delete from sys_role where role_id in (${new Array(ids.length)
      .fill('?')
      .join(',')})`;
    let [{ affectedRows: role_affectedRows }] = await poolPromise.execute(delete_role_sql, ids);
    if (!role_affectedRows) {
      return res.status(500).json({
        code: 500,
        msg: '删除角色失败',
        data: null,
      });
    }

    res.status(200).json({
      code: 200,
      msg: '删除角色成功',
      data: null,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * 修改角色
 */
async function updateRole(req, res, next) {
  if (validateParams({ req, res, validationResult })) return;
  try {
    const { role_id, role_name, role_key, role_sort, remark } = req.body;
    const [[{ count }]] = await poolPromise.query(
      `select count(role_name) as count from sys_role where role_id!=? and role_name=?`,
      [role_id, role_name]
    );
    if (count)
      return res.status(httpStatusCode.Conflict).json({
        code: httpStatusCode.Conflict,
        msg: '角色名已存在',
        data: null,
      });
    const { nickname } = req.auth;
    const update_role_sql = `update sys_role set role_name = ?,role_key = ?,role_sort = ?,remark = ?,update_by = ? where role_id = ?`;
    let [{ affectedRows: role_affectedRows }] = await poolPromise.execute(update_role_sql, [
      role_name,
      role_key,
      role_sort,
      remark,
      nickname,
      role_id,
    ]);
    if (!role_affectedRows) {
      return res.status(500).json({
        code: 500,
        msg: '修改角色失败',
        data: null,
      });
    }
    res.status(200).json({
      code: 200,
      msg: '修改角色成功',
      data: null,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * 修改角色状态
 */
async function updateRoleStatus(req, res, next) {
  if (validateParams({ req, res, validationResult })) return;
  try {
    const { role_id, status } = req.body;
    const update_role_sql = `update sys_role set status = ? where role_id = ?`;
    let [{ affectedRows: role_affectedRows }] = await poolPromise.execute(update_role_sql, [
      status,
      role_id,
    ]);
    if (!role_affectedRows) {
      return res.status(500).json({
        code: 500,
        msg: '修改角色状态失败',
        data: null,
      });
    }
    res.status(200).json({
      code: 200,
      msg: '修改角色状态成功',
      data: null,
    });
  } catch (error) {
    next(error);
  }
}

/**
 * 获取角色 已选菜单
 * @param {*} req
 * @param {*} res
 * @param {*} next
 */
async function selectRoleSelectedMenu(req, res, next) {
  if (validateParams({ req, res, validationResult })) return;

  try {
    const { role_id } = req.params;
    // 查出该角色权限标识
    const [[{ role_key }]] = await poolPromise.execute(
      `select role_key from sys_role where role_id = ?`,
      [role_id]
    );

    let select_menu_sql = `select distinct m.menu_id, m.menu_name from sys_menu m
        left join sys_role_menu r_m on m.menu_id = r_m.menu_id`;
    // 超级管理员获取全部,其他角色只能获取自己拥有的
    if (role_key !== config.SuperAdmin) {
      select_menu_sql += ` where r_m.role_id = ?`;
    }
    const [list] = await poolPromise.execute(select_menu_sql, [role_id]);
    res.status(httpStatusCode.Ok).json({
      code: httpStatusCode.Ok,
      msg: '获取角色已选菜单成功',
      data: list.map((item) => item.menu_id),
    });
  } catch (error) {
    next(error);
  }
}

/**
 * 修改角色 已选菜单
 * @param {*} req
 * @param {*} res
 * @param {*} next
 */
async function updateRoleSelectedMenu(req, res, next) {
  if (validateParams({ req, res, validationResult })) return;
  const connection = await poolPromise.getConnection();
  try {
    // await connection.startTransaction // TAG: 开启事务
    await connection.beginTransaction();
    const { role_id, menuIds } = req.body;
    const delete_role_menu_sql = `delete from sys_role_menu where role_id = ?`;
    await connection.execute(delete_role_menu_sql, [role_id]);

    // 给文章添加标签
    // const tag_placeholder = tag_ids.map(() => "(?,?)").join(","); // 标签占位符
    // const insert_tag_ids = tag_ids.flatMap((id) => [newArticleId, id]); // 占位对应id
    // const insert_article_tag_sql = `insert into article_tags(article_id,tag_id) values ${tag_placeholder}`;
    const placeholders = menuIds.map(() => '(?,?)').join(',');
    const insert_role_menu_val = menuIds.flatMap((id) => [role_id, id]);
    const insert_role_menu_sql = `insert into sys_role_menu(role_id, menu_id) values ${placeholders}`;
    await connection.execute(insert_role_menu_sql, insert_role_menu_val);

    await connection.commit();
    res.status(httpStatusCode.Ok).json({
      code: httpStatusCode.Ok,
      msg: '角色已选菜单更新成功',
      data: null,
    });
  } catch (error) {
    await connection.rollback();
    next(error);
  } finally {
    connection.release();
  }
}

module.exports = {
  selectRoleList,
  insertRole,
  deleteRole,
  updateRole,
  updateRoleStatus,
  selectRoleSelectedMenu,
  updateRoleSelectedMenu,
};
